package fab.forms 
{
	import fab.forms.error.FormError;
	import fab.forms.error.FormErrorEvent;
	import fab.forms.error.ServerError;
	import fab.forms.error.ServerErrorEvent;
	import fab.forms.fields.CheckBoxElement;
	import fab.forms.fields.DateElement;
	import fab.forms.fields.Element;
	import fab.forms.fields.InputTextElement;
	import fab.forms.fields.RadioButtonGroupElement;
	import fl.controls.CheckBox;
	import fl.controls.RadioButton;
	import flash.display.DisplayObject;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.HTTPStatusEvent;
	import flash.events.IEventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.MouseEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLRequestMethod;
	import flash.net.URLVariables;
	import flash.text.TextField;
	import flash.utils.Dictionary;
	/**
	 * ...
	 * @author fab
	 */

	public class Form extends EventDispatcher
	{
		public var testretourok:Boolean=false;
		static public const CLICKSUBMIT:String = "clicksubmit";
		static public const SUBMIT:String = "submit";
		static public const RECEIPT:String = "receipt";
		static public const DATE:String = "DATE";
		private var loader:URLLoader;
		private var request:URLRequest;
		private var submitbtn:DisplayObject;
		private var _elements:Dictionary;
		private var _conditions:Array;
		private var servererrors:Vector.<ServerError>;
		//private var _errors:Array;
		
		public function Form(url:String, method:String=URLRequestMethod.POST) 
		{
            loader = new URLLoader();
            configureListeners(loader);
            request = new URLRequest(url);
			request.method = method;
			_elements = new Dictionary();
			_conditions = new Array();
			servererrors = new Vector.<ServerError>();
		}
		
		public function addElement(...args):void
		{
			var field:Element;
			if ( args[0] is TextField )
			{
				field = new InputTextElement( args[0], args[ 1 ] );
			}
			else if ( args[0] is CheckBox )
			{
				field = new CheckBoxElement( args[0], args[ 1 ] );
			}
			else if ( args[0] is RadioButton )
			{
				(args[0] as RadioButton).groupName = args[ 1 ];
				(args[0] as RadioButton).value = args[ 2 ];
				field = RadioButtonGroupElement.getByGroup( args[0] as RadioButton );
			}	
			else if ( args[0] is String )
			{
				switch( args[0 ] )
				{
					case DATE:
					args.shift();
					field = new DateElement( args.shift(), args );
					break;
				}
			}				
			else {
				trace("type d'élément non reconnu", args[0] );
				return;
			}
			_elements[ field.name ] = field;
		}		
		//public function addCondition( condition : AbstractCondition, id : String, errorCode : String ) : void
		//{
			//condition.errorCode = errorCode ; 
			//condition.name = id ; 
			//condition.addEventListener( ElementErrorEvent.FIELD_ERROR, _fieldErrorHandler ) ; 			
			//_conditions.push( condition ) ; 
		//}
		public function addSubmit(sp:DisplayObject):void
		{
			
			submitbtn = sp;
			submitbtn.addEventListener( MouseEvent.CLICK, click_submit );
			
		}
		
		public function addFormerror(errorid:String, elementid:String, errortype:String, errormessage:String=""):void
		{
			var element:Element = _elements[ elementid ] as Element;
			var error:FormError = new FormError( errorid, errortype, errormessage, element );
			element.addError( error );
			//_errors.push( error );
		}
		
		public function addServererror( errorid:String, errortype:String, errormessage:String ):void
		{
			servererrors.push( new ServerError( errorid, errortype, errormessage ) );
		}
		
		
		private function click_submit(e:MouseEvent):void 
		{
			dispatchEvent( new Event( CLICKSUBMIT ) );
			var errors: Vector.<FormError> = validation();
			if ( errors.length > 0 )
			{
				//trace("errors", errors );
				dispatchEvent( new FormErrorEvent( errors[ 0 ].id, errors[ 0 ] ) );// n'execute que la premiere !
			}
			else {
				submit();
			}
		}
		/*
		 * pour ne tester la validation d'une partie des éléments
		 * @params les elementid:String à tester
		 * @return le vecteur des erreurs
		 * effet : dispatchEvent des erreurs
		 * */
		public function testElements(...args): Vector.<FormError>
		{
			var errors : Vector.<FormError> = new  Vector.<FormError>() ; 
			for each ( var elementid : String in args ) 
			{
				var element:Element = _elements[ elementid ] as Element;
				var error:FormError = element.validate();
				//trace(error)
				if ( error ) 
				{
					errors.push(error) ;
				}
			}
			if ( errors.length > 0 )
			{
				//trace("errors", errors );
				dispatchEvent( new FormErrorEvent( errors[ 0 ].id, errors[ 0 ] ) );// n'execute que la premiere !
			}
			else {
				
			}	
			return errors ; 			
		}		
		/*public function testErrors(...args): Vector.<FormError>
		{
			var errors : Vector.<FormError> = new  Vector.<FormError>() ; 
			for each ( var errorid : String in args ) 
			{
				var error:FormError = FormError.getById( errorid )
				trace(error)
				//TODO
			}
			return errors ; 			
		}*/
		private function validation(): Vector.<FormError>
		{
			var errors : Vector.<FormError> = new  Vector.<FormError>() ; 
			
			for each ( var element : Element in _elements ) 
			{
				var error:FormError = element.validate();
				//trace(error)
				if ( error ) 
				{
					errors.push(error) ;
				}
			}
			//
			//for each ( var c : AbstractCondition in _conditions ) 
			//{
				//if (  !c.match() ) 
				//{
					//out.push( new ElementError(null, c.errorCode, _messager.get( c.errorCode, null )) ) ;	
					//errs ++ ; 
				//}
			//}
			
			return errors ; 
		}
		
		private function submit():void
		{
			dispatchEvent( new Event( SUBMIT ) );
			var variables:URLVariables = new URLVariables();
			
			for each( var field:Element in _elements )
			{
				variables[ field.name ] = field.getValue();
			}
			//variables.alea = Math.random();
			request.data = variables;
			trace("variables", variables);
			
			if ( testretourok )
			{
				dispatchEvent( new Event( RECEIPT ) );
			}
			else try {
                loader.load(request);
            } catch (error:Error) {
                trace("Unable to load requested document.");
            }				
		}
	

        private function configureListeners(dispatcher:IEventDispatcher):void {
            dispatcher.addEventListener(Event.COMPLETE, completeHandler);
            dispatcher.addEventListener(Event.OPEN, openHandler);
            dispatcher.addEventListener(ProgressEvent.PROGRESS, progressHandler);
            dispatcher.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
            dispatcher.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
            dispatcher.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
        }

        private function completeHandler(event:Event):void {
            var loader:URLLoader = URLLoader(event.target);
            trace("completeHandler: " + loader.data);
    
			var errors: Vector.<ServerError> = server_validation( loader.data );
			if ( errors.length > 0 && errors[ 0 ] != null )
			{
				dispatchEvent( new ServerErrorEvent( errors[ 0 ].id, errors[ 0 ] ) );
			}
			else {
				//success
				dispatchEvent( new Event( RECEIPT ) );
			}
			
        }
		private function server_validation(data:*): Vector.<ServerError>
		{
			var errors : Vector.<ServerError> = new  Vector.<ServerError>() ; 
			var returnxml:XML = new XML( data );
			//if ( returnxml.mess_err != "" )// Actiplay skyrock noel ---------
			
			if ( returnxml.@result != "ok" )// TODO chercher comment on fait avec XML dans le déjà fait
			{trace("popo", returnxml.error);
				errors.push( new ServerError( returnxml.error.code, returnxml.error.code, returnxml.error.msg ) );
				//errors.push( ServerError.getById( returnxml.mess_err ) );
			}
			return errors;
		}

        private function openHandler(event:Event):void {
            //trace("openHandler: " + event);
        }

        private function progressHandler(event:ProgressEvent):void {
            //trace("progressHandler loaded:" + event.bytesLoaded + " total: " + event.bytesTotal);
        }

        private function securityErrorHandler(event:SecurityErrorEvent):void {
            //trace("securityErrorHandler: " + event);
        }

        private function httpStatusHandler(event:HTTPStatusEvent):void {
            //trace("httpStatusHandler: " + event);
        }

        private function ioErrorHandler(event:IOErrorEvent):void {
            //trace("ioErrorHandler: " + event);
        }
    }	

}